
`timescale 1 ns / 1 ps

module vga_dma_ip_v1_0_vtg #(
     // Users to add parameters here
     parameter integer VLINES   = 525,//vga_disp_hvcnt[15:0] ; //行数=521
     parameter integer HPIXELS  = 800,//vga_disp_hvcnt[31:16]; //行像素点=800
     parameter integer HL_PIXS  = 96,//vga_disp_hvcnt[31:16]; //行像素点=800
     parameter integer VL_LINES = 2,//vga_disp_hvcnt[31:16]; //行像素点=800
     parameter integer HBP      = 144,//vga_disp_hconf[15:0] ; //行显示后沿=144(96+48)
     parameter integer HFP      = 784,//vga_disp_hconf[31:16]; //行显示前沿=784（96+48+640）
     parameter integer VBP      = 35, //vga_disp_vconf[15:0] ; //场显示后沿=36(2+33)
     parameter integer VFP      = 515 //vga_disp_vconf[31:16]; //场显示前沿=511（2+33
)(
     // Users to add ports here
     input wire clk_vga,  
     input wire rst    ,
     
     output wire[4:0] R,
     output wire[5:0] G,
     output wire[4:0] B,
     output wire vga_pclk,
                   
     output reg vga_h_sync,  
     output reg vga_v_sync,
     // User ports fifo
    
     output wire        fifo_rd_clk,
     output wire        fifo_rd_en,
     input  wire        fifo_empty,
     input  wire [31:0] fifo_dout,

     output wire        vga_de,
     output reg         data_err
);
// Add user logic here
//--------------------------------------------------------
reg [9:0] h_counter;
reg [9:0] v_counter;

reg vs_enable;
always@(posedge clk_vga ) vs_enable<=(h_counter==HPIXELS)?1:0; 
//行同步信号计数器
//--------------------------------------------------------
always @(posedge clk_vga,posedge rst) begin
    if(rst)begin 
        h_counter<=0;//计数器复位
    end 
    else if(h_counter==HPIXELS) begin
        h_counter<=0;//计数器复位
    end
    else begin
        h_counter<=h_counter+1;
    end
end
//场同步信号计数器
always @(posedge clk_vga,posedge rst) begin
    if(rst)begin 
        v_counter<=0;//计数器复位
    end 
    else if(vs_enable==1) begin
        v_counter<=(v_counter==VLINES)?0:(v_counter+1);
    end 
end
//当v_counter为0或1时，场同步脉冲为低电平
//当h_counter为0--127时，行同步脉冲为低电平
reg h_sync;
reg v_sync;
always@(posedge clk_vga) h_sync   <= (h_counter<HL_PIXS)?0:1;
always@(posedge clk_vga) v_sync   <= (v_counter<VL_LINES)?0:1;
//--------------------------------------------------------
assign fifo_rd_clk  = clk_vga;
assign fifo_rd_en   = (h_counter<HFP)&&(h_counter>=HBP)&&(v_counter<VFP)&&(v_counter>=VBP);    
//--------------------------------------------------------
reg in_disp_area;
always@(posedge clk_vga) in_disp_area <= fifo_rd_en; 
//--------------------------------------------------------
reg in_disp_area_ff1;
always@(posedge clk_vga) in_disp_area_ff1 <= in_disp_area; 
//--------------------------------------------------------
reg[31:0] fifo_dout_ff1;
always@(posedge clk_vga) fifo_dout_ff1 <= fifo_dout;
//--------------------------------------------------------
reg[24:0] rgb_raw_data;
always @(posedge clk_vga,posedge rst) begin
    if(rst)begin
        rgb_raw_data <= 24'b0;
    end
    else if(in_disp_area)begin
        rgb_raw_data <= fifo_dout_ff1[23:0];
    end
    else begin
        rgb_raw_data <= 24'b0;
    end
end
//--------------------------------------------------------
reg data_eof_flag;
always @(posedge clk_vga,posedge rst) begin
    if(rst)begin 
        data_eof_flag <= 1'b0;
    end 
    else if(in_disp_area)begin
        data_eof_flag <= (fifo_dout_ff1[31])?1'b1:data_eof_flag;
    end
    else begin
        data_eof_flag <= 1'b0;
    end
end 
//--------------------------------------------------------
// delay 1 cycle  
reg pre_h_sync;
reg pre_v_sync;
always@(posedge clk_vga) pre_h_sync   <= h_sync;
always@(posedge clk_vga) pre_v_sync   <= v_sync;   
//--------------------------------------------------------
// delay 2 cycle  
always@(posedge clk_vga) vga_h_sync   <= pre_h_sync;
always@(posedge clk_vga) vga_v_sync   <= pre_v_sync;  
//--------------------------------------------------------
reg[7:0] data_eof_cntr;  
//--------------------------------------------------------
always @(posedge clk_vga,posedge rst) begin
    if(rst)begin 
        data_eof_cntr <= 8'b0;   
    end 
    else if(data_eof_flag) begin 
        data_eof_cntr <= data_eof_cntr + 8'h1;     
    end 
    else begin
        data_eof_cntr <= 8'b0;   
    end
end 
//--------------------------------------------------------
reg fifo_empty_ff1;
reg fifo_empty_ff2;
always @(posedge clk_vga) fifo_empty_ff1 <= fifo_empty;
always @(posedge clk_vga) fifo_empty_ff2 <= fifo_empty_ff1;
//--------------------------------------------------------
reg data_err_report_v;
//--------------------------------------------------------
always @(posedge clk_vga,posedge rst) begin
    if(rst)begin 
        data_err_report_v <= 1'b0;   
    end 
    else if(fifo_empty_ff1&(~fifo_empty_ff2))begin 
        data_err_report_v <= 1'b1;   
    end 
end  
//--------------------------------------------------------
always @(posedge clk_vga,posedge rst) begin
    if(rst)begin 
        data_err <= 1'b0;
    end 
    else if(data_err_report_v) begin 
        if(fifo_rd_en) begin
            data_err <= fifo_empty?1'b1:data_err;
        end 
        else if(data_eof_cntr > 1) begin
            data_err <= 1'b1;
        end
    end
end     
//--------------------------------------------------------
assign R = rgb_raw_data[7:3];
assign G = rgb_raw_data[15:10];
assign B = rgb_raw_data[23:19];

assign vga_de     = in_disp_area_ff1;
assign vga_pclk   = clk_vga;
// User logic ends

endmodule

